
#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BGroupBox>

#include "StringUtils.h"
#include "HingeConstraintPanel.h"

HingeConstraintPanel::HingeConstraintPanel(BWidget* parent) : BWidget(parent)
{
	BGridLayout* topLayout = new BGridLayout();
	{
		_nameAEdit = new BLineEdit();
		_pivotAEdit = new BLineEdit();
		_axisAEdit = new BLineEdit();
		_nameBEdit = new BLineEdit();
		_pivotBEdit = new BLineEdit();
		_axisBEdit = new BLineEdit();

		topLayout->setWidget(0, 0, new BLabel("nameA"));
		topLayout->setWidget(0, 1, _nameAEdit);
		topLayout->setWidget(1, 0, new BLabel("pointA"));
		topLayout->setWidget(1, 1, _pivotAEdit);
		topLayout->setWidget(2, 0, new BLabel("axisA"));
		topLayout->setWidget(2, 1, _axisAEdit);
		topLayout->setWidget(3, 0, new BLabel("nameB"));
		topLayout->setWidget(3, 1, _nameBEdit);
		topLayout->setWidget(4, 0, new BLabel("pointB"));
		topLayout->setWidget(4, 1, _pivotBEdit);
		topLayout->setWidget(5, 0, new BLabel("axisB"));
		topLayout->setWidget(5, 1, _axisBEdit);
	}

	BGroupBox* angularGroupBox = new BGroupBox("Angular Limit");
	{
		BLabel* softnessLabel = new BLabel("Softness");
		_limitSoftnessSpinBox = new BRealSpinBox();

		BLabel* biasFactorLabel = new BLabel("Bias Factor");
		_biasFactorSpinBox = new BRealSpinBox();

		BLabel* relaxFactorLabel = new BLabel("Relax Factor");
		_relaxFactorSpinBox = new BRealSpinBox();

		BLabel* minimumLabel = new BLabel("minimum");
		_minimumSpinBox = new BRealSpinBox();

		BLabel* maximumLabel = new BLabel("maximum");
		_maximumSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(angularGroupBox);
		gridLayout->setWidget(1, 0, softnessLabel);
		gridLayout->setWidget(1, 1, _limitSoftnessSpinBox);
		gridLayout->setWidget(2, 0, biasFactorLabel);
		gridLayout->setWidget(2, 1, _biasFactorSpinBox);
		gridLayout->setWidget(3, 0, relaxFactorLabel);
		gridLayout->setWidget(3, 1, _relaxFactorSpinBox);
		gridLayout->setWidget(4, 0, minimumLabel);
		gridLayout->setWidget(4, 1, _minimumSpinBox);
		gridLayout->setWidget(5, 0, maximumLabel);
		gridLayout->setWidget(5, 1, _maximumSpinBox);
	}
	_motorGroupBox = new BGroupBox("Motor");
	_motorGroupBox->setCheckable(true);
	_motorGroupBox->setChecked(true);
	{
		BLabel* targetVelocityLabel = new BLabel("Target Velocity");
		_targetVelocitySpinBox = new BRealSpinBox();

		BLabel* maxImpulseLabel = new BLabel("Max Impulse");
		_maxImpulseSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(_motorGroupBox);
		gridLayout->setWidget(2, 0, targetVelocityLabel);
		gridLayout->setWidget(2, 1, _targetVelocitySpinBox);
		gridLayout->setWidget(3, 0, maxImpulseLabel);
		gridLayout->setWidget(3, 1, _maxImpulseSpinBox);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(topLayout);
	vlayout->addWidget(angularGroupBox);
	vlayout->addWidget(_motorGroupBox);

	connect(this, Signal_AssetChanged, &HingeConstraintPanel::slotAssetChanged);

	connect(_nameAEdit, Signal_EditFinished, &HingeConstraintPanel::slotNameAEditFinished);
	connect(_pivotAEdit, Signal_EditFinished, &HingeConstraintPanel::slotPivotAEditFinished);
	connect(_axisAEdit, Signal_EditFinished, &HingeConstraintPanel::slotAxisAEditFinished);
	connect(_nameBEdit, Signal_EditFinished, &HingeConstraintPanel::slotNameBEditFinished);
	connect(_pivotBEdit, Signal_EditFinished, &HingeConstraintPanel::slotPivotBEditFinished);
	connect(_axisBEdit, Signal_EditFinished, &HingeConstraintPanel::slotAxisBEditFinished);

	connect(_limitSoftnessSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotLimitSoftnessEditFinished);
	connect(_biasFactorSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotLimitBiasEditFinsihed);
	connect(_relaxFactorSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotLimitRelaxFactorEditFinihsed);
	connect(_minimumSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotLimitMinimumEditFinished);
	connect(_maximumSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotLimitMaximumEditFinished);
	connect(_motorGroupBox, Signal_Toggled, &HingeConstraintPanel::slotMotorEnabledToggled);
	connect(_targetVelocitySpinBox, Signal_EditFinished, &HingeConstraintPanel::slotTargetVelocityEditFinished);
	connect(_maxImpulseSpinBox, Signal_EditFinished, &HingeConstraintPanel::slotMaxImpulseEditFinished);
}
HingeConstraintPanel::~HingeConstraintPanel()
{

}

void HingeConstraintPanel::slotAssetChanged(BObject* object, const BValue& value)
{
	_hingeConstraint = value;
	if (_hingeConstraint)
	{
		_nameAEdit->setText(_hingeConstraint->nodeA()->name());
		_pivotAEdit->setText(StringFromVector(_hingeConstraint->pointA()));
		_axisAEdit->setText(StringFromVector(_hingeConstraint->axisA()));
		_nameBEdit->setText(_hingeConstraint->nodeB()->name());
		_pivotBEdit->setText(StringFromVector(_hingeConstraint->pointB()));
		_axisBEdit->setText(StringFromVector(_hingeConstraint->axisB()));

		const BAngleLimit& angleLimit = _hingeConstraint->angleLimit();
		_limitSoftnessSpinBox->setValue(angleLimit.softness());
		_biasFactorSpinBox->setValue(angleLimit.biasFactor());
		_relaxFactorSpinBox->setValue(angleLimit.relaxFactor());
		_minimumSpinBox->setValue(angleLimit.low());
		_maximumSpinBox->setValue(angleLimit.high());
		_motorGroupBox->setChecked(_hingeConstraint->motorEnabled());
		_targetVelocitySpinBox->setValue(_hingeConstraint->motorTargetVelocity());
		_maxImpulseSpinBox->setValue(_hingeConstraint->motorMaxImpulse());
	}
}

void HingeConstraintPanel::slotNameAEditFinished(BObject* object, const BValue& value)
{
	const BString& name = value;
	_hingeConstraint->nodeA()->setName(name);
}
void HingeConstraintPanel::slotPivotAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointA = StringToVector(text);
	_hingeConstraint->setPointA(pointA);
}
void HingeConstraintPanel::slotAxisAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& axisA = StringToVector(text);
	_hingeConstraint->setAxisA(axisA);
}
void HingeConstraintPanel::slotNameBEditFinished(BObject* object, const BValue& value)
{
	const BString& name = value;
	_hingeConstraint->nodeB()->setName(name);
}
void HingeConstraintPanel::slotPivotBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointB = StringToVector(text);
	_hingeConstraint->setPointB(pointB);
}
void HingeConstraintPanel::slotAxisBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& axisB = StringToVector(text);
	_hingeConstraint->setAxisB(axisB);
}

void HingeConstraintPanel::slotLimitSoftnessEditFinished(BObject* object, const BValue& value)
{
	BReal softness = value;
	BAngleLimit limit = _hingeConstraint->angleLimit();
	limit.setSoftness(softness);
	_hingeConstraint->setAngleLimit(limit);
}
void HingeConstraintPanel::slotLimitBiasEditFinsihed(BObject* object, const BValue& value)
{
	BReal biasFactor = value;
	BAngleLimit limit = _hingeConstraint->angleLimit();
	limit.setBiasFactor(biasFactor);
	_hingeConstraint->setAngleLimit(limit);
}
void HingeConstraintPanel::slotLimitRelaxFactorEditFinihsed(BObject* object, const BValue& value)
{
	BReal relaxFactor = value;
	BAngleLimit limit = _hingeConstraint->angleLimit();
	limit.setRelaxFactor(relaxFactor);
	_hingeConstraint->setAngleLimit(limit);
}
void HingeConstraintPanel::slotLimitMinimumEditFinished(BObject* object, const BValue& value)
{
	BReal low = value;
	BAngleLimit limit = _hingeConstraint->angleLimit();
	limit.setRange(low, limit.high());
	_hingeConstraint->setAngleLimit(limit);
}
void HingeConstraintPanel::slotLimitMaximumEditFinished(BObject* object, const BValue& value)
{
	BReal high = value;
	BAngleLimit limit = _hingeConstraint->angleLimit();
	limit.setRange(limit.low(), high);
	_hingeConstraint->setAngleLimit(limit);
}
void HingeConstraintPanel::slotMotorEnabledToggled(BObject* object, const BValue& value)
{
	bool motorEnabled = value;
	_hingeConstraint->setMotorEnabled(motorEnabled);
}
void HingeConstraintPanel::slotTargetVelocityEditFinished(BObject* object, const BValue& value)
{
	BReal targetVelocity = value;
	_hingeConstraint->setMotorTargetVelocity(targetVelocity);
}
void HingeConstraintPanel::slotMaxImpulseEditFinished(BObject* object, const BValue& value)
{
	BReal maxImpulse = value;
	_hingeConstraint->setMotorMaxImpulse(maxImpulse);
}
